package com.sky.service.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.entity.Orders;
import com.sky.exception.BaseException;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.util.StringUtil;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrderMapper orderMapper;
    // 营业额统计
    @Override
    public TurnoverReportVO getTurnoverStatistics(LocalDate begin, LocalDate end) {
        TurnoverReportVO turnoverReportVO = new TurnoverReportVO();
        String turnoverList = "";
        String DateList = "";
        //1.把日期区间的每一天存入List
        List<LocalDate> dateArrayList = new ArrayList<>();
        while (!begin.equals(end)) {
            dateArrayList.add(begin);
            // 下一天的
            begin = begin.plusDays(1);
        }
        // StringUtils.join(),把集合转换为字符串，用逗号分隔
        String dateList = StringUtils.join(dateArrayList, ",");
        log.info("[日期列表] {}", dateList);
        // 2.遍历日期列表，查询每日的销售额
        List<Double> turnoverArrayList = new ArrayList<>();
        for (LocalDate localDate : dateArrayList) {
            // 获取每天的起始时间
            LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);
            // 调用Mapper
            Map queryParam = new HashMap();
            queryParam.put("status", Orders.COMPLETED);
            queryParam.put("beginTime", beginTime);
            queryParam.put("endTime", endTime);
            Double sumResult = orderMapper.selectByMap(queryParam);
            if (sumResult == null) {
                sumResult = 0d;
            }
            turnoverArrayList.add(sumResult);
        }
        turnoverList = StringUtils.join(turnoverArrayList,",");
        log.info("[营业额列表] {}",turnoverList );

        turnoverReportVO.setTurnoverList(turnoverList);
        turnoverReportVO.setDateList(dateList);
        return turnoverReportVO;
    }

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserReportVO getUserStatistics(LocalDate begin, LocalDate end) {
        UserReportVO userReportVO = new UserReportVO();
        userReportVO.setDateList("4-22,4-23,4-24,4-25,4-26");
        userReportVO.setNewUserList("10,5,12,22,100");
        userReportVO.setTotalUserList("110,115,127,149,249");
        // 1.把日期期间的每一天存入列表
        List<LocalDate> dateArrayList = new ArrayList<>();
        while (!begin.equals(end)) {
            dateArrayList.add(begin);
            begin = begin.plusDays(1);
        }
        // 把最后一天存入列表
        dateArrayList.add(end);
        // 2.遍历日期列表，获取每天新增用户数及累计用户总数
        List<Long> newArrayList = new ArrayList<>();
        List<Long> totalArrayList = new ArrayList<>();
        for (LocalDate currDate : dateArrayList) {
            // 构建当前的最大时间和最小时间
            LocalDateTime beginTime = LocalDateTime.of(currDate, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(currDate, LocalTime.MAX);
            // 获取每天的新增用户数量

            Long newUserCount = getUser(beginTime,endTime);

            // 获取每天的累计用户总数量
            Long totalUserCount = getUser(null, endTime);

            newArrayList.add(newUserCount);
            totalArrayList.add(totalUserCount);
        }
        // 3.返回前端需要的字符串
        userReportVO.setDateList(StringUtils.join(dateArrayList, ","));
        userReportVO.setNewUserList(StringUtils.join(newArrayList, ","));
        userReportVO.setTotalUserList(StringUtils.join(totalArrayList, ","));
        return userReportVO;
    }

    private Long getUser(LocalDateTime beginTime, LocalDateTime endTime) {
        Map queryParam = new HashMap();
        queryParam.put("beginTime", beginTime);
        queryParam.put("endTime", endTime);
        Long userCount = userMapper.selectCountByMap(queryParam);
        if (userCount == null){
            userCount = 0L;
        }
        return userCount;
    }

    // 订单统计
    @Override
    public OrderReportVO getOrdersStatistics(LocalDate begin, LocalDate end) {
        OrderReportVO orderReportVO = new OrderReportVO();
        //1.把日期区间放入列表
        List<LocalDate> dateArrayList = new ArrayList<>();
        while (!begin.equals(end)) {
            dateArrayList.add(begin);
            begin = begin.plusDays(1);
        }
        //把最后一天存入列表
        dateArrayList.add(end);
        // 2.遍历日期列表，计算每天的订单总数量及有效数量（数据库）
        List<Long> validArrayList = new ArrayList<>();
        List<Long> totalArrayList = new ArrayList<>();
        Long totalCount = 0L;
        Long validCount = 0L;
        for (LocalDate currDate : dateArrayList) {
            LocalDateTime beginDateTime = LocalDateTime.of(currDate, LocalTime.MIN);
            LocalDateTime endDateTime = LocalDateTime.of(currDate, LocalTime.MAX);
            // 使用公共方法，获取订单数量
            // 先获取有效订单
            Long validOrderCount = getOrderCount(beginDateTime,endDateTime,Orders.COMPLETED);
            Long totalOrderCount = getOrderCount(beginDateTime,endDateTime,null);
            // 累计有效订单数和总的订单数
            validCount = validCount + validOrderCount;
            totalCount = totalCount+totalOrderCount;

            // 把每天获取的订单总数量和有效数量存入列表
            validArrayList.add(validOrderCount);
            totalArrayList.add(totalOrderCount);
        }
        // 3.准备前端需要的数据（java代码的逻辑）

        orderReportVO.setDateList(StringUtils.join(dateArrayList,","));

        orderReportVO.setValidOrderCount(validCount.intValue());
        orderReportVO.setTotalOrderCount(totalCount.intValue());
        double completionRate = 1.0*validCount/totalCount;
        orderReportVO.setOrderCompletionRate(completionRate);
        orderReportVO.setValidOrderCountList(StringUtils.join(validArrayList,","));
        orderReportVO.setOrderCountList(StringUtils.join(totalArrayList,","));

        return orderReportVO;
    }

    private Long getOrderCount(LocalDateTime beginTime, LocalDateTime endTime, Integer completed) {
        // 根据日期区间，查询数据库，获取订单数据量
        Map queryParam = new HashMap();
        queryParam.put("beginTime", beginTime);
        queryParam.put("endTime", endTime);
        queryParam.put("status", completed);
        Long count = orderMapper.selectByCount(queryParam);
        return count!=null ? count : 0L;
    }

    @Override
    public SalesTop10ReportVO getSalesTop10(LocalDate begin, LocalDate end) {
        SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
        // 调用
        List<GoodsSalesDTO> goodsSalesDTOList = orderMapper.selectSalesTop10(begin, end);
        // 遍历结果集，存储名字列表与份数列表
        List<String> nameList = new ArrayList<>();
        List<Integer> numberList = new ArrayList<>();
        for (GoodsSalesDTO goods : goodsSalesDTOList) {
            nameList.add(goods.getName());
            numberList.add(goods.getNumber());
        }
        salesTop10ReportVO.setNameList(StringUtils.join(nameList,","));
        salesTop10ReportVO.setNumberList(StringUtils.join(numberList,","));
        return salesTop10ReportVO;
    }

    @Autowired
    private WorkspaceService workspaceService;

    // 导出数据运营报表
    @Override
    public void export(HttpServletResponse response) {
        // 读取模板文件
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("excel\\运营数据报表模板.xlsx");

        try {
            //构建Excel
            XSSFWorkbook excel = new XSSFWorkbook(inputStream);
            //操作excel
            // 构建时间区间
            LocalDate begin = LocalDate.now().minusDays(30);
            LocalDate end = LocalDate.now().minusDays(1);
            // 获取30天的总运营数据
            LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
            BusinessDataVO businessData = workspaceService.getBusinessData(beginTime, endTime);
            log.info("[----------]{}",businessData);
            //把数据写道Excel表中
            XSSFSheet sheet = excel.getSheetAt(0);
            // 定位单元格
            sheet.getRow(1).getCell(1).setCellValue(begin + "至" + end);
            //定位到第四行
            XSSFRow row = sheet.getRow(3);
            // 营业额
            row.getCell(2).setCellValue(businessData.getTurnover());
            row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessData.getNewUsers());
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessData.getValidOrderCount());
            row.getCell(4).setCellValue(businessData.getUnitPrice());
            // 获取30天的详细数据（具体每天的数据）
            for (int i = 0; i < 30 ; i++) {
                // 获取当天的开始与结束
                LocalDate currDate = begin.plusDays(i);
                // 构建一天的开始时间与结束时间
                beginTime = LocalDateTime.of(currDate,LocalTime.MIN);
                endTime = LocalDateTime.of(currDate,LocalTime.MAX);
                businessData = workspaceService.getBusinessData(beginTime, endTime);
                // 定位行
                row = sheet.getRow(7+i);
                row.getCell(1).setCellValue(currDate+"");
                row.getCell(2).setCellValue(businessData.getTurnover());
                row.getCell(3).setCellValue(businessData.getValidOrderCount());
                row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessData.getUnitPrice());
                row.getCell(6).setCellValue(businessData.getNewUsers());
            }

            //把excel发送给客户端
            ServletOutputStream outputStream = response.getOutputStream();
            // 客户端开始收
            excel.write(outputStream);
            //关闭资(自己创建的)
            inputStream.close();
            excel.close();
        } catch (IOException e) {
            e.printStackTrace();
            throw  new BaseException("导出报表出错," + e.getMessage());
        }
    }
}
